#include "Rational.h"
#include <cstdlib>
#include <iostream>

Rational::Rational(int nominator, int denominator) {
    if (denominator < 0) {
        denominator *= -1;
        nominator *= -1;
    }
    this->nominator = nominator;
    this->denominator = denominator;
    this->normalize();
}

Rational::Rational(const Rational& r) {
    this->nominator = r.nominator;
    this->denominator = r.denominator;
}

Rational& Rational::operator =(const Rational& r) {
    if(this != &r){
        Rational(r).sw(*this);
    }
    return *this;
}

Rational& Rational::operator *=(const Rational& r) {
    this->nominator *= r.nominator;
    this->denominator *= r.denominator;
    this->normalize();
    return *this;
}

Rational& Rational::operator /=(const Rational& r) {
    this->nominator *= r.denominator;
    this->denominator *= r.nominator;
    this->normalize();
    return *this;
}

Rational& Rational::operator -=(const Rational& r) {
    this->denominator *= r.denominator;
    this->nominator = this->nominator * r.denominator - r.nominator * this->denominator;
    this->normalize();
    return *this;
}

Rational& Rational::operator +=(const Rational& r) {
    this->denominator *= r.denominator;
    this->nominator = this->nominator * r.denominator + r.nominator * this->denominator;
    this->normalize();
    return *this;
}

Rational& Rational::operator ++() {
    this->nominator += this->denominator;
    return *this;
}

Rational Rational::operator ++(int) {
    Rational result(*this);
    ++(*this);
    return result;
}

Rational& Rational::operator --() {
    this->nominator -= this->denominator;
    return *this;
}

Rational Rational::operator --(int) {
    Rational result(*this);
    --(*this);
    return result;
}

Rational::operator double() {
    return ((double) this->nominator) / this->denominator;
}

int Rational::get_nominator() const {
    return this->nominator;
}

int Rational::get_denominator() const {
    return this->denominator;
}

void Rational::normalize() {
    int n = gcd(this->nominator, this->denominator);
    this->nominator /= n;
    this->denominator /= n;
}

void Rational::sw(Rational& r)
{
    std::swap(this->nominator, r.nominator);
    std::swap(this->nominator, r.denominator);
}


Rational operator+ (const Rational& a, const Rational& b) {
    Rational r(a);
    r += b;
    return r;
}

Rational operator- (const Rational& a, const Rational& b) {
    Rational r(a);
    r -= b;
    return r;
}

Rational operator* (const Rational& a, const Rational& b) {
    Rational r(a);
    r *= b;
    return r;
}

Rational operator/ (const Rational& a, const Rational& b) {
    Rational r(a);
    r /= b;
    return r;
}

bool operator== (const Rational& a, const Rational& b) {
    return (a.get_nominator() == b.get_nominator()) && (a.get_denominator() == b.get_denominator());
}

bool operator!= (const Rational& a, const Rational& b) {
    return !(a == b);
}

bool operator<= (const Rational& a, const Rational& b) {
    return a == b || a < b;
}

bool operator>= (const Rational& a, const Rational& b) {
    return a == b || a > b;
}

bool operator<  (const Rational& a, const Rational& b) {
    return (a - b).get_nominator() < 0;
}

bool operator>  (const Rational& a, const Rational& b) {
    return (a - b).get_nominator() > 0;
}



int gcd(int a, int b) {
    a = std::abs(a);
    b = std::abs(b);
    while (a != b) {
        if (a == 0) {
            return b;
        }
        if (b == 0) {
            return a;
        }
        if (a > b) {
            a = a % b;
        } else {
            b = b % a;
        }
    }
    return a;
}

int main(){
    Rational a(12,9);
    Rational b(2,5);
    Rational c(0,1);
    Rational e(12,-3);
    std::cout << double(b) << std::endl;
    std::cout << (a < b ) << " " << (a == b) << " " << (a != b) << std::endl;
    std::cout << "c " << c;
    std::cout << "e " << e << std::endl;
    std::cout << "a++ " << a++ << " ";
    std::cout << a << std::endl;
    std::cout << "a-- " << a-- << " ";
    std::cout << a << std::endl;
    std::cout << "++a " << ++a << " ";
    std::cout << a << std::endl;
    --a;
    a *= b;
    std::cout << a << std::endl;
    a /= b;
    std::cout << a << std::endl;
    std::cout << (a*b) << std::endl;
    return 0;
}